package com.chushouya.order.service.api.impl;

import com.general.framework.core.enums.IEnum;
import com.general.framework.core.exception.BusinessException;
import com.chushouya.order.constants.CancelOrderProcessEnum;
import com.chushouya.order.constants.DoorToDoorOrderProcessEnum;
import com.chushouya.order.constants.ExpressOrderProcessEnum;
import com.chushouya.order.constants.OrderTypeEnum;
import com.chushouya.order.dto.api.order.OrderInfoApiDTO;
import com.chushouya.order.dto.api.order.OrderProcessApiDTO;
import com.chushouya.order.dto.api.order.OrderProcessStepDTO;
import com.chushouya.order.service.api.OrderApiService;
import com.chushouya.order.service.api.OrderProcessApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

@Service
@Slf4j
public class OrderProcessApiServiceImpl implements OrderProcessApiService {

    @Resource
    private OrderApiService orderApiService;

    @Override
    public OrderProcessApiDTO getOrderProcess(String orderNo) {
        log.info("开始获取订单流程信息，订单号: {}", orderNo);
        
        // 参数校验
        if (!StringUtils.hasText(orderNo)) {
            throw new BusinessException("订单号不能为空");
        }
        
        try {
            // 获取订单信息
            OrderInfoApiDTO orderInfo = orderApiService.userOrderDetail(orderNo);
            if (orderInfo == null) {
                throw new BusinessException("订单不存在: " + orderNo);
            }
            
            OrderProcessApiDTO result = new OrderProcessApiDTO();
            result.setOrderNo(orderNo);
            result.setOrderType(orderInfo.getOrderType());
            result.setCurrentStatus(orderInfo.getOrderStatus());
            
            // 根据订单类型构建对应的流程
            buildOrderProcess(result, orderInfo);
            
            log.info("订单流程信息获取成功，订单号: {}, 订单类型: {}, 当前状态: {}", 
                    orderNo, orderInfo.getOrderType(), orderInfo.getOrderStatus());
            
            return result;
        } catch (Exception e) {
            log.error("获取订单流程信息失败，订单号: {}", orderNo, e);
            throw e;
        }
    }

    /**
     * 根据订单类型构建订单流程
     */
    private void buildOrderProcess(OrderProcessApiDTO result, OrderInfoApiDTO orderInfo) {
        Integer orderType = orderInfo.getOrderType();
        Integer currentStatus = orderInfo.getOrderStatus();
        
        // 检查是否为取消状态的订单
        if (isCancelledOrder(currentStatus)) {
            // 取消订单流程 - 将所有取消状态映射为CANCEL_ORDER状态(20)
            buildCancelOrderProcess(result, currentStatus);
            return;
        }
        
        if (Objects.equals(OrderTypeEnum.EXPRESS_RECYCLE.value(), orderType)) {
            // 邮寄订单流程
            buildProcessSteps(result, currentStatus, 
                    Arrays.asList(ExpressOrderProcessEnum.values()),
                    ExpressOrderProcessEnum::get);
        } else if (Objects.equals(OrderTypeEnum.DOOR_RECYCLE.value(), orderType)) {
            // 上门订单流程
            buildProcessSteps(result, currentStatus,
                    Arrays.asList(DoorToDoorOrderProcessEnum.values()),
                    DoorToDoorOrderProcessEnum::get);
        } else {
            throw new BusinessException("不支持的订单类型: " + orderType);
        }
    }

    /**
     * 判断是否为取消状态的订单
     * 取消状态包括: CANCELLED(20), CLOSED(21), TIMEOUT(22), BACKOUT_AUDITING(23), 
     * BACKOUT_CLOSED(24), CLERK_CANCEL(25), RETURN_CLOSED(26), CMCC_CANCEL(27), CHARGE_CLOSE(28)
     */
    private boolean isCancelledOrder(Integer orderStatus) {
        if (orderStatus == null) {
            return false;
        }
        // 取消状态范围: 20-28
        return orderStatus >= 20 && orderStatus <= 28;
    }

    /**
     * 构建取消订单流程
     */
    private void buildCancelOrderProcess(OrderProcessApiDTO result, Integer originalStatus) {
        // 使用CANCEL_ORDER状态(20)作为当前状态来构建流程
        Integer processStatus = CancelOrderProcessEnum.CANCEL_ORDER.value();
        
        // 构建流程步骤
        buildProcessSteps(result, processStatus,
                Arrays.asList(CancelOrderProcessEnum.values()),
                CancelOrderProcessEnum::get);
        
        // 重新设置当前状态描述，使用原始状态的描述
        try {
            // 导入OrderStatusEnum来获取原始状态描述
            result.setCurrentStatusDesc(getOriginalStatusDesc(originalStatus));
        } catch (Exception e) {
            log.warn("获取原始状态描述失败，使用默认描述: {}", originalStatus, e);
            result.setCurrentStatusDesc("订单取消");
        }
    }

    /**
     * 获取原始状态描述
     */
    private String getOriginalStatusDesc(Integer status) {
        // 这里需要根据实际的OrderStatusEnum来获取描述
        // 由于我们已经知道状态码对应的描述，直接映射
        switch (status) {
            case 20: return "已取消";
            case 21: return "已关闭";
            case 22: return "超时关闭";
            case 23: return "撤单审核中";
            case 24: return "已撤单";
            case 25: return "业务员取消";
            case 26: return "退货关闭";
            case 27: return "店员关闭";
            case 28: return "退单关闭";
            default: return "订单取消";
        }
    }

    /**
     * 通用的流程步骤构建方法
     * @param result 结果对象
     * @param currentStatus 当前状态
     * @param allSteps 所有流程步骤
     * @param enumGetter 枚举获取函数
     */
    private <T extends IEnum<Integer>> void buildProcessSteps(OrderProcessApiDTO result, 
                                                              Integer currentStatus,
                                                              List<T> allSteps,
                                                              Function<Integer, T> enumGetter) {
        if (currentStatus == null) {
            log.warn("订单状态为空，使用默认状态");
            currentStatus = 0;
        }
        
        // 设置当前状态信息
        T currentEnum = enumGetter.apply(currentStatus);
        if (currentEnum != null) {
            result.setCurrentStatusDesc(currentEnum.named());
            if (currentEnum instanceof ExpressOrderProcessEnum) {
                result.setCurrentStatusText(((ExpressOrderProcessEnum) currentEnum).getStatusText());
            } else if (currentEnum instanceof DoorToDoorOrderProcessEnum) {
                result.setCurrentStatusText(((DoorToDoorOrderProcessEnum) currentEnum).getStatusText());
            } else if (currentEnum instanceof CancelOrderProcessEnum) {
                result.setCurrentStatusText(((CancelOrderProcessEnum) currentEnum).getStatusText());
            }
        }
        
        // 获取当前状态在流程中的位置
        int currentIndex = findCurrentIndex(allSteps, currentStatus);
        
        // 构建流程步骤
        List<OrderProcessStepDTO> processSteps = new ArrayList<>(allSteps.size());
        List<OrderProcessStepDTO> completedSteps = new ArrayList<>();
        
        for (int i = 0; i < allSteps.size(); i++) {
            T step = allSteps.get(i);
            OrderProcessStepDTO stepDTO = createStepDTO(step, i, currentIndex);
            processSteps.add(stepDTO);
            
            // 添加到已完成步骤列表
            if (stepDTO.getCompleted()) {
                completedSteps.add(stepDTO);
            }
        }
        
        result.setProcessSteps(processSteps);
        result.setCompletedSteps(completedSteps);
    }

    /**
     * 查找当前状态在流程中的位置
     */
    private <T extends IEnum<Integer>> int findCurrentIndex(List<T> allSteps, Integer currentStatus) {
        for (int i = 0; i < allSteps.size(); i++) {
            if (Objects.equals(allSteps.get(i).value(), currentStatus)) {
                return i;
            }
        }
        log.warn("未找到匹配的流程状态: {}, 默认为第一个状态", currentStatus);
        return 0;
    }

    /**
     * 创建流程步骤DTO
     */
    private <T extends IEnum<Integer>> OrderProcessStepDTO createStepDTO(T step, int index, int currentIndex) {
        OrderProcessStepDTO stepDTO = new OrderProcessStepDTO();
        stepDTO.setStatus(step.value());
        stepDTO.setDesc(step.named());
        stepDTO.setStepOrder(index + 1);
        stepDTO.setCurrent(index == currentIndex);
        stepDTO.setCompleted(index <= currentIndex);
        
        // 设置状态文本
        if (step instanceof ExpressOrderProcessEnum) {
            stepDTO.setStatusText(((ExpressOrderProcessEnum) step).getStatusText());
        } else if (step instanceof DoorToDoorOrderProcessEnum) {
            stepDTO.setStatusText(((DoorToDoorOrderProcessEnum) step).getStatusText());
        } else if (step instanceof CancelOrderProcessEnum) {
            stepDTO.setStatusText(((CancelOrderProcessEnum) step).getStatusText());
        }
        
        return stepDTO;
    }
}
